package cn.yzgy.yzgyoa.common.shiro;

import cn.yzgy.yzgyoa.common.crsp.StatusCode;
import cn.yzgy.yzgyoa.common.crsp.Urmf;
import cn.yzgy.yzgyoa.common.utils.IpUtil;
import cn.yzgy.yzgyoa.ucenter.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 解决Shrio在前后端分离项目中 未认证会跳转的问题
 *
 * 未认证、权限不足情况下，返回JSON
 *
 * @author Yqsen
 * @version 0.0.1
 * @since 2019-8-21 10:39:46
 *
 */
@Slf4j
public class YzAuthorizationFilter extends FormAuthenticationFilter {

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
        httpServletResponse.setContentType("application/Json");
        httpServletResponse.setCharacterEncoding("UTF-8");

        PrintWriter responseMsg = httpServletResponse.getWriter();
        String requestMethod = httpServletRequest.getMethod();
        String requestUri = httpServletRequest.getRequestURI();
        String remoteIp = IpUtil.getIpAddr(httpServletRequest);
        Subject subject = this.getSubject(request, response);
        if (subject.getPrincipal() == null) {
            log.warn("USER_NOT_AUTHENTICATION_WARN: {} {} FROM {} ",
                    requestMethod,
                    requestUri,
                    remoteIp);
            httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
            responseMsg.println(Urmf.fail(httpServletRequest.getRequestURI(), StatusCode.UN_AUTHORIZATION));
        } else {
            SysUser user = (SysUser)subject.getPrincipal();
            log.warn("USER_ACCESS_DENIED: USER:{} {} {} FROM {} ",
                    user.getLoginName(),
                    requestMethod,
                    requestUri,
                    remoteIp);
            httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
            responseMsg.println(Urmf.fail(httpServletRequest.getRequestURI(), StatusCode.FORBIDDEN));
        }
        responseMsg.flush();
        responseMsg.close();
        return false;
    }
}
